package com.zebra.remoting;


import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

import java.util.concurrent.atomic.AtomicBoolean;

public abstract class AbstractRemotingServer implements RemotingServer {
    private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractRemotingServer.class);

    private AtomicBoolean started = new AtomicBoolean(false);

    public boolean start(int port){
        if (port < 0 || port > 65535) {
            throw new IllegalArgumentException(String.format(
                    "Illegal port value: %d, which should between 0 and 65535.", port));
        }

        if (started.compareAndSet(false, true)) {
            try {
                doInit();
                logger.warn("Prepare to start server on port {} ", port);
                if (doStart(port)) {
                    logger.info("Server started on port {}", port);
                    return true;
                } else {
                    logger.warn("Failed starting server on port {}", port);
                    return false;
                }
            } catch (Throwable t) {
                this.stop();// do stop to ensure close resources created during doInit()
                throw new IllegalStateException("ERROR: Failed to start the Server!", t);
            }
        } else {
            String errMsg = "ERROR: The server has already started!";
            logger.error(errMsg);
            throw new IllegalStateException(errMsg);
        }
    }

    public boolean stop(){
        if (started.compareAndSet(true, false)) {
            return this.doStop();
        } else {
            throw new IllegalStateException("ERROR: The server has already stopped!");
        }
    }

    protected abstract void doInit();
    protected abstract boolean doStart(int port) throws InterruptedException;
    protected abstract boolean doStop();


}
